package com.xsherl.leetcode.solution;

import com.xsherl.leetcode.utils.PrintUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class ValidNumber {


    /**
     *
     * @param s
     * 1 <= s.length <= 20
     * s 仅含英文字母（大写和小写），数字（0-9），加号 '+' ，减号 '-' ，或者点 '.' 。
     */
    public boolean isNumber(String s) {
        int step = 0;
        int i = 0;
        boolean[] show = new boolean[7];
        while (i < s.length()){
            char c = s.charAt(i);
            if (step == 0){
                if (c == '+' || c == '-'){
                    i++;
                    show[0] = true;
                }
                step++;
            } else if (step == 1){
                if (c < '0' || c > '9'){
                    step++;
                } else {
                    i++;
                    show[1] = true;
                }
            } else if (step == 2){
                if (c == '.'){
                    i++;
                    show[2] = true;
                }
                step++;
            } else if (step == 3){
                if (c < '0' || c > '9'){
                    step++;
                } else {
                    i++;
                    show[3] = true;
                }
            } else if (step == 4){
                if (c == 'e' || c == 'E') {
                    i++;
                    show[4] = true;
                }
                step++;
            } else if (step == 5){
                if (c == '+' || c == '-'){
                    i++;
                    show[5] = true;
                }
                step++;
            } else if (step == 6){
                if (c < '0' || c > '9'){
                    return false;
                }
                i++;
                show[6] = true;
            }
        }
        PrintUtils.println(show);
        // 如果只有一个符号并且不是整数返回false
        if (i == 1 && !show[1]){
            return false;
        }
        // 如果'.' 前后都没有数字，返回 false
        if (show[2] && !show[1] && !show[3]){
            return false;
        }
        // 如果'e' 或 ‘E’前或者后面没有数字，返回 false
        if (show[4] && (!show[6] || (!show[1] && !show[3]))){
            return false;
        }
        // 如果'+'、‘-’前面没有'e' 或 ‘E’，返回 false
        if (show[5] && !show[4]){
            return false;
        }
        return true;
    }

    /**
     * 定有限状态自动机
     */
    public boolean isNumber1(String s) {
        Map<State, Map<CharType, State>> transfer = new HashMap<>();
        transfer.put(State.STATE_INIT, new HashMap<CharType, State>(){{
            put(CharType.CHAR_SIGN, State.STATE_SIGN);
            put(CharType.CHAR_NUMBER, State.STATE_INT);
            put(CharType.CHAR_DOT, State.STATE_DOT_WITHOUT_PRE_INT);
        }});
        transfer.put(State.STATE_SIGN, new HashMap<CharType, State>(){{
            put(CharType.CHAR_NUMBER, State.STATE_INT);
            put(CharType.CHAR_DOT, State.STATE_DOT_WITHOUT_PRE_INT);
        }});
        transfer.put(State.STATE_INT, new HashMap<CharType, State>(){{
            put(CharType.CHAR_NUMBER, State.STATE_INT);
            put(CharType.CHAR_DOT, State.STATE_DOT);
            put(CharType.CHAR_EXP, State.STATE_EXP);
        }});
        transfer.put(State.STATE_DOT_WITHOUT_PRE_INT, new HashMap<CharType, State>(){{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
        }});
        transfer.put(State.STATE_DOT, new HashMap<CharType, State>(){{
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
        }});
        transfer.put(State.STATE_FRACTION, new HashMap<CharType, State>(){{
            put(CharType.CHAR_EXP, State.STATE_EXP);
        }});
        transfer.put(State.STATE_EXP, new HashMap<CharType, State>(){{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_INT);
            put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
        }});
        transfer.put(State.STATE_EXP_SIGN, new HashMap<CharType, State>(){{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_INT);
        }});
        transfer.put(State.STATE_EXP_INT, new HashMap<CharType, State>(){{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_INT);
        }});
        State state = State.STATE_INIT;
        for (int i = 0; i < s.length(); ++i){
            CharType charType = toCharType(s.charAt(i));
            State state1 = transfer.get(state).get(charType);
            if (state1 == null){
                return false;
            }
            state = state1;
        }
        return state == State.STATE_INT
                || state == State.STATE_DOT
                || state == State.STATE_FRACTION
                || state == State.STATE_EXP_INT;
    }

    private CharType toCharType(char c){
        if (c == '+' || c == '-'){
            return CharType.CHAR_SIGN;
        }
        if (c >= '0' && c <= '9'){
            return CharType.CHAR_NUMBER;
        }
        if (c == 'e' || c == 'E'){
            return CharType.CHAR_EXP;
        }
        if (c == '.'){
            return CharType.CHAR_DOT;
        }
        return CharType.CHAR_ILLEGAL;
    }

    enum State {
        // 初始状态
        STATE_INIT,
        STATE_SIGN,
        STATE_INT,
        STATE_FRACTION,
        STATE_DOT,
        STATE_DOT_WITHOUT_PRE_INT,
        STATE_EXP,
        STATE_EXP_SIGN,
        STATE_EXP_INT,
    }

    enum CharType {
        CHAR_SIGN,
        CHAR_NUMBER,
        CHAR_DOT,
        CHAR_EXP,
        CHAR_ILLEGAL
    }

    public static void main(String[] args) {
        String s = "+05047e+6";
        boolean number = new ValidNumber().isNumber1(s);
        System.out.println(number);
    }

}
